--
-- @Author:      name
-- @DateTime:    2018-03-30 23:05:48
-- @Description: 节点内消息的处理

local skynet = require "skynet"


local MessageHandler = class("MessageHandler")

---------------------------------------------------------
-- Private
---------------------------------------------------------
function MessageHandler:ctor(message_dispatch, node_message)

	self.server_id = tonumber(skynet.getenv("server_id")) --节点名
	self.proto_file = skynet.getenv("proto_config") --proto文件路径	
    self.server_type = skynet.getenv("server_type") 
    self.server_name = skynet.getenv("server_name") 
    self.cluster_addr = skynet.getenv("cluster_addr")
    self.cluster_name = skynet.getenv("cluster_name")
    
    self.node_cluster_id = skynet.getenv("node_cluster_id")


	self.message_dispatch = message_dispatch	
	self.node_message = node_message

	self:register()
	
end

--注册本服务里的消息
function MessageHandler:register()
	self.message_dispatch:registerSelf('start', handler(self, self.start))


    self.message_dispatch:registerSelf('server_info_nt', handler(self,self.serverInfoNt))

    self.message_dispatch:registerSelf('assign_server_req', handler(self,self.onAssignServerReq))	
    self.message_dispatch:registerSelf('assign_game_server_req', handler(self,self.onAssignGameServer))   
    
    --在线信息
    self.message_dispatch:registerSelf('game_online_info_req', handler(self, self.onHandlerQueryGameOnlineInfo))
    self.message_dispatch:registerSelf('room_info_nt', handler(self, self.onHandleGameRoomInfo))
    self.message_dispatch:registerSelf('desk_info_nt', handler(self, self.onHandleGameRoomDeskInfo))
    
end



--分配网关服务器
function MessageHandler:assignGateServer(user_id, protocol)
    local server = nil
    local is_server_started = false
    local user_assign_info = self.assign_manager:getUserAssign(user_id)
    print("____user_assign_info__",user_assign_info)
    if user_assign_info and user_assign_info.gate_server_id and user_assign_info.gate_server_id > 0 then

        local gate_server = self.server_manager:getServer(user_assign_info.gate_server_id)
        if gate_server then
            is_server_started = true
            server = gate_server
        end

    end

    --进行分配
    if not server then
        local min_client_count_ratio = 1.0

        local gate_server_list = self.server_manager:getServerList()
        for _, gate_server in pairs(gate_server_list) do
            if gate_server.server_name=="游戏网关" and gate_server.server_addr then
                is_server_started = true
                print("________gate_server__",gate_server)
                if gate_server.online_count < gate_server.max_client then
                    local client_count_ratio = gate_server.online_count / gate_server.max_client
                    if client_count_ratio < min_client_count_ratio then
                        --人数最少的服务器
                        min_client_count_ratio = client_count_ratio
                        server = gate_server
                    end
                end
            end
        end
    end

    return server, is_server_started
end

--分配大厅服务器
function MessageHandler:assignHallServer(user_id)
    local server = nil
    local is_server_started = false
    local user_assign_info = self.assign_manager:getUserAssign(user_id)

    if user_assign_info and user_assign_info.hall_server_id and user_assign_info.hall_server_id > 0 then
        local hall_server = self.server_manager:getServer(user_assign_info.hall_server_id)
        if hall_server then
            is_server_started = true
            server = hall_server
        end
    end

    --进行分配
    if not server then
        local min_online_count_ratio = 1.0
        local hall_server_list = self.server_manager:getHallServerList()
        for _, hall_server in pairs(hall_server_list) do
            is_server_started = true
            if hall_server.online_count < hall_server.max_client then
                local online_count_ratio = hall_server.online_count / hall_server.max_client
                if online_count_ratio < min_online_count_ratio then
                    min_online_count_ratio = online_count_ratio
                    server = hall_server
                end
            end
        end
    end

    return server, is_server_started
end

--分配游戏服务器
function MessageHandler:assignGameServer(user_id, game_id, group_id)
    local server = nil
    local is_server_started = false
    local assign_info = self.assign_manager:getUserAssign(user_id)
    --已分配置游戏服务器
    if assign_info and assign_info.game_server_id and assign_info.game_server_id > 0 then
        local server_info = self.server_manager:getServer(assign_info.game_server_id)
        local room_info = self.game_manager:getGameRoomInfo(assign_info.game_server_id, group_id)
        if server_info and room_info and room_info.game_id == game_id then
            return server_info
        end
    end

    --进行分配, 人数少的服务器优先
    local min_ratio = 1.0
    local server_list = self.server_manager:getGameServerList()
    -- print("_________server_list___",server_list)
    for _, game_server in pairs(server_list) do
        local room_info = self.game_manager:getGameRoomInfo(game_server.server_id, group_id)
        -- print("______room_info___",room_info)
        if room_info and room_info.game_id == game_id then
            if game_server.online_count < game_server.max_client then
                local online_ratio = game_server.online_count / game_server.max_client
                if online_ratio < min_ratio then
                    min_ratio = online_ratio
                    server = game_server
                end
            end
        end
    end
    return server
end

--分配游戏桌子
function MessageHandler:assignGameRoomDesk(user_id, server_id, group_id)
    local desk_info = nil
    local user_assign_info = self.assign_manager:getUserAssign(user_id)
    if user_assign_info and user_assign_info.desk_id and user_assign_info.desk_id~=0 then
        desk_info = self.game_manager:getGameRoomDesk(server_id, user_assign_info.desk_id)        
    end
    --进行分配
    if not desk_info then
        local game_room = self.game_manager:getGameRoomInfo(server_id, group_id)
        local game_room_desk_list = self.game_manager:getGameRoomDeskList(server_id)
        -- print("____game_room_desk_list__",game_room_desk_list)
        for _, desk in pairs(game_room_desk_list) do
            -- print("__2222222_______",group_id==desk.group_id, desk.group_id)
            if group_id==desk.group_id and desk.sit_down_count < desk.player_count then
                desk_info = desk
                -- print("__2222222____desk_info___",desk_info)
                break
            end
        end
    end
    return desk_info
end












---------------------------------------------------------
-- CMD
---------------------------------------------------------
function MessageHandler:start()
	
    self.assign_manager = global.assign_manager
    self.game_manager = global.game_manager

    self.server_manager = global.server_manager    
    self.node_message = global.node_message
    self.server_info = global.server_info
    self.user_manager = global.user_manager
    self.cluster_manager = global.cluster_manager


    self.cluster_manager:serverRegister()
end


-- 各个服务器信息写到reids
function MessageHandler:serverInfoNt(msg_data)
    print("_____MessageHandler:serverInfoNt =", msg_data)

    --把相关信息写到redis
    local server_info = msg_data
    local key = "server_info:" ..server_info.server_type..":"..server_info.server_id
    self.node_message:callDbRedis("hmset", { key, server_info })
    if not self.server_manager:addServer(server_info) then 
        --更新服务器信息
        self.server_manager:updateServer(server_info)
    end
    -- print("_____:serverInfoNt =", self.server_manager:getServerList())

end


-- 分配网关服务器
function MessageHandler:onAssignServerReq(msg_data)

    print("_____zone_分配网关服务器________",msg_data)
 
    local user_id = msg_data.user_id
    local token = msg_data.token
    local protocol = msg_data.protocol

    local gate_server_id = 0
    local gate_server_addr = ""
    local gate_server_port 
    local gate_server_wport
    local hall_server_id = 0
    local update_time = os.time()

    --分配处理
    local assign_result = 1
    local gate_server, is_server_started = self:assignGateServer(user_id, protocol)
    local hall_server = nil
    print("___11111_______gate_server__", gate_server, is_server_started)
    if gate_server then
        hall_server, is_server_started = self:assignHallServer(user_id)
    end
    print("___2222_______hall_server__", hall_server, is_server_started)
    if gate_server and hall_server then
        gate_server_id = gate_server.server_id
        gate_server_addr = gate_server.server_addr
        hall_server_id = hall_server.server_id
        gate_server_port = gate_server.server_port
        gate_server_wport = gate_server.server_wport
        assign_result = 0
    end

    --消息
    local assign_sever_result = nil
    if assign_result == 0 then
        --把相关信息写到redis
        local server_user_info = 
        {
            user_id = user_id,
            token = token,
            gate_server_id = gate_server_id,            
            gate_server_addr = gate_server_addr,
            gate_server_port = gate_server_port,
            gate_server_wport = gate_server_wport,
            hall_server_id = hall_server_id,
            update_time = update_time,
        }
        self.node_message:callDbProxy("executeRedis", "hmset", {"server_info:user:" .. user_id, server_user_info})

        local user_assign_info = {
            user_id = user_id,
            gate_server_id = gate_server_id,            
            hall_server_id = hall_server_id,
            update_time = update_time,
        }
        if not self.assign_manager:addUserAssign(user_assign_info) then
            self.assign_manager:updateUserAssign(user_assign_info)
        end
        --通知nodeserver
        self.node_message:sendNodeProxy(self.node_cluster_id, "assign_sever_nt", user_assign_info)
        --通知网关
        
        assign_sever_result = {
            error_code = assign_result,
            error_msg = "分配网关服务器成功",

            user_id = user_id,
            token = token,        
            server_id = gate_server_id,
            server_type	= "gateserver",
            server_name = "游戏网关",
            server_addr = gate_server_addr,
            server_port = gate_server_port,
            server_wport = gate_server_wport,            
        }


    else
        local error_msg = is_server_started and "分配服务器失败" or "服务器未开启"
        assign_sever_result = {
            error_code = assign_result,
            error_msg = error_msg,
            user_id = user_id,
        }
    end

    --发送分配消息
    --self.node_message:callNodeServer(router.src_type, router.src_id, 0, self.cmd.DMSG_MDM_ZONE, self.cmd.MSG_Z2L_AssignGateServerResult, assign_sever_result)
    print("___assign_sever_result___",assign_sever_result)
    return assign_sever_result
end

--分配游戏服务器,桌子
function MessageHandler:onAssignGameServer(msg_data)
    print("______MessageHandler:onHandleAssignGameServer___游戏房间分配写入redis________",msg_data)    
    local user_id = msg_data.user_id    
    local game_id = msg_data.game_id  --游戏id  
    local group_id = msg_data.group_id  --场次id
    local des_desk_id = msg_data.desk_id --目标桌子id

    local gate_server_id --网关服务器id
    local gate_server_addr 
    local game_server_id 
    local desk_id
    local update_time = os.time()

    --获取网关信息
    local user_assign = self.assign_manager:getUserAssign(user_id)
    gate_server_id = user_assign.gate_server_id
    local gate_cluster_name = "gateserver_"..gate_server_id
    --分配处理
    local assign_result = 1
    local game_server = self:assignGameServer(user_id, game_id, group_id)
    local desk_info = nil
    if game_server then
        desk_info = self:assignGameRoomDesk(user_id, game_server.server_id, group_id)
    end
    if game_server and desk_info then
        game_server_id = game_server.server_id
        desk_id = desk_info.desk_id
        assign_result = 0
    end

    --分配游戏服务器结果
    local assign_game_server_res = nil
    if assign_result==0 then
        --把相关信息写到redis
        local server_user_info = 
        {
            user_id = user_id,
            game_server_id = game_server_id,
            game_id = game_id,
            group_id = group_id,
            desk_id = desk_id,
            update_time = update_time,
        }
        self.node_message:callDbProxy("executeRedis", "hmset", {"server_info:user:" .. user_id, server_user_info}) 

        --玩家分配信息
        local user_assign_info = {
            user_id = user_id,
            game_server_id = game_server_id,
            game_id = game_id,
            group_id = group_id,
            desk_id = desk_id,
            update_time = update_time,
        }
        if not self.assign_manager:addUserAssign(user_assign_info) then
            self.assign_manager:updateUserAssign(user_assign_info)
        end

        assign_game_server_res = {
            error_code = assign_result,
            error_msg = "分配游戏服务器成功",

            user_id = user_id,
            game_id = game_id,
            group_id = group_id,

            desk_id = desk_id,
            server_id = game_server.server_id,
            server_type = game_server.server_type,
            server_name = game_server.server_name,
            cluster_addr = game_server.cluster_addr,

            gate_server_id = user_assign.gate_server_id,
            -- gate_server_addr = gate_server_addr,
        }   
        --通知nodeserver
        local user_assign_info = {
            user_id = user_id,
            game_server_id = game_server_id,
            desk_id = desk_id,
        }
        self.node_message:sendNodeProxy(self.node_cluster_id, "assign_sever_nt", user_assign_info)
   
    else
        local error_msg = "分配游戏服务器失败或游戏服务器未开启"
        assign_game_server_res = {
            error_code = assign_result,
            error_msg = error_msg,

            user_id = user_id,
            game_id = game_id,
            group_id = group_id,
        }
    end

    return assign_game_server_res
end

-- 查询游戏在线信息
function MessageHandler:onHandlerQueryGameOnlineInfo(msg_data)
    -- print("MessageHandler:onHandlerQueryGameOnlineInfo =", msg_data)
    
    -- local router = msg_data.router
    local msg_boby = msg_data
    local query_type = msg_boby.query_type
    local game_id = msg_boby.game_id 
    local group_id = msg_boby.group_id 

    local online_list = {}
    if query_type == 1 then --查找指定游戏的在线信息
        local info = {}
        info.game_id = game_id
        info.group_id = group_id
        info.online_count = 0

        local game_server_list = self.server_manager:getGameServerList()
        for _, game_server in pairs(game_server_list) do
            local game_room = self.game_manager:getGameRoom(game_server.server_id)
            if game_room and game_room.game_id == game_id and game_room.group_id == group_id then
                info.online_count = info.online_count + game_server.online_count
            end
        end

        table.insert(online_list, info)
    end

    local res = {
        error_code = 0,
        game_online_list = online_list,
    }

    return res
end

-- 游戏房间信息
function MessageHandler:onHandleGameRoomInfo(msg_data)
    -- print("MessageHandler:onHandleGameRoomInfo =", msg_data)
    local server_id = msg_data.server_id
    --把相关信息写到redis
    local game_room_info = msg_data
    local key = "server_info:game:room:" .. server_id 
    self.node_message:callDbProxy("executeRedis", "hmset", { key, game_room_info })
    self.game_manager:addGameRoom(game_room_info)
end

-- 游戏房间桌子信息
function MessageHandler:onHandleGameRoomDeskInfo(msg_data)
    -- print("MessageHandler:onHandleGameRoomDeskInfo =", msg_data)

    -- local router = msg_data.router
    local msg_boby = msg_data
    local server_id = msg_boby.server_id
    local game_id = msg_boby.game_id
    local group_id = msg_boby.group_id
    local desk_id = msg_boby.desk_id

    --把相关信息写到redis
    local desk_info = 
    {
        server_id = msg_boby.server_id,
        server_type = msg_boby.server_type,
        game_id = msg_boby.game_id,
        group_id = msg_boby.group_id,

        desk_id = msg_boby.desk_id,
        player_count = msg_boby.player_count,
        sit_down_count = msg_boby.sit_down_count,
        game_started = msg_boby.game_started,
    }

    local key = "server_info:game:room:" .. server_id  .. ":desk:" .. desk_id
    self.node_message:callDbProxy("executeRedis", "hmset", { key, desk_info })

    if not self.game_manager:addGameRoomDesk(server_id, desk_info) then
        self.game_manager:updateGameRoomDesk(server_id, desk_info)
    end
end









return MessageHandler